package com.ruike.alisurface.serialport;


import com.ruike.alisurface.utils.GsonUtils;
import com.voodoo.lib_logcat.L;
import com.voodoo.lib_utils.SharedUtils;
import com.voodoo.serialport.util.ByteUtils;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


/**
 * 转动出货信息返回值解析上传类
 */
public class ShopInfoUtils {
    public interface SlotCallBacK {
        void onSlotSuccess(String serilamsg, byte[] resultBytes);

        void onSlotFail(int slotindex);
    }

    public SlotCallBacK slotCallBacK;

    public void setSlotCallBacK(SlotCallBacK slotCallBacK) {
        this.slotCallBacK = slotCallBacK;
    }

    Timer timer;//倒计时
    private static ShopInfoUtils shopInfoUtils;

    public static ShopInfoUtils getInstance() {
        if (shopInfoUtils == null) {
            synchronized (ShopInfoUtils.class) {
                if (shopInfoUtils == null) {
                    shopInfoUtils = new ShopInfoUtils();
                }
            }
        }
        return shopInfoUtils;
    }


    /**
     * 类型及货道号
     *
     * @param type
     * @param slotindex
     */
    public void TodoShipmentSlot(int slotindex, int type, int turnNumber) {
        if (type == 21001 || type == 0) {  //弹簧货到
            setSlotShop(slotindex, 0, turnNumber);
        } else if (type == 21002 || type == 2) {//蛇形货道
            setSlotShop(slotindex, 2, turnNumber);
        } else if (type == 21003 || type == 1) {//电磁锁
            setSlotShop(slotindex, 1, turnNumber);
        }else if (type == 21004 || type == 3) {//推板货道
            setSlotShop(slotindex, 3, turnNumber);
        } else {
            L.i("--货道类型异常- ", slotindex);
        }
    }


    /**
     * 出货及延迟
     *
     * @param slotindex
     * @param type
     */
    public void setSlotShop(int slotindex, int type, int turnNumber) {
        L.i("    出货数量=" + turnNumber);

        Ttys3Utils.getInstance().outGoods(slotindex - 1, type, turnNumber);
        Timercancal();
        timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                L.i("出货倒计时完成   取消计时，开始下一次出货");
                if (timer != null) {
                    timer.cancel();
                    timer = null;
                    EventBus.getDefault().post(new MsgEventBus("出货倒计时完成", "出货计时到" + (turnNumber * 10000 / 1000) + "秒 ，结束计时@" + (slotindex - 1)));
                }
                if (slotCallBacK != null) {
                    slotCallBacK.onSlotFail(slotindex);
                }
            }
        };
        timer.schedule(timerTask, turnNumber * 10000);


    }

    public void Timercancal() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    String Is_O;

    /**
     * 上传解析好的数据列表上传到MQTT后台
     * <p>
     * 上报的报文
     * topic: rkt/mch/checkoutnotify/
     * jsonContent:
     * {
     * "oid" : "订单号",
     * "Is_O" : int 是否在线 2离线 1在线,
     * "dl" : "出货项目 xxx x x x每一项出货请求包含6位 其中前三位表示货道编号 第四位表示货道检测数量 第五位表示电机转动数量 最后一位表示货道类型，每条数据之间用竖线隔开 （0,弹簧货道 1,电磁锁 2,履带 如果为1时，不判断弹掉货检测无报修提示）",
     * "RT" : "十六进制 转动时间字符串，和DL字段相对应，DL字段中每个货道的每次转动都会对应到该字符串中",
     * "MV" : "十六进制 主柜体版本号 包含程序更新日期（0~6位）以及电路板生产日期（7~12位）",
     * "T" : "十六进制 温控板版本号 包含程序更新日期（0~6位）以及电路板生产日期（7~12位）",
     * "Fir" : "十六进制 第一副柜版本号 包含程序更新日期（0~6位）以及电路板生产日期（7~12位）",
     * "Sec" : "十六进制 第二副柜版本号 包含程序更新日期（0~6位）以及电路板生产日期（7~12位）",
     * "Thi" : "十六进制 第三副柜版本号 包含程序更新日期（0~6位）以及电路板生产日期（7~12位）"
     * }
     * 示例：
     * {
     * "oid":"2018112114100000022522",
     * "Is_O":2,
     * "dl":"001010|002010|003020|004010|005010",
     * "RT":"19161c1c1c1c",
     * "MV":"130a09130713",
     * "T":"130a09130713",
     * "Fir":"130a09130713",
     * "Sec":"130a09130713",
     * "Thi":"130a09130713"
     * }
     * <p>
     *
     * @param oid        orderId
     * @param mqttClient {@link MqttAndroidClient}
     */
    public void sendCheckoutnotify(String oid, MqttAndroidClient mqttClient) {
        StringBuilder dlStringBuilder = new StringBuilder();
        StringBuilder rtStringBuilder = new StringBuilder();
        HashMap<String, String> map = BzVersion();
        map.put("oid", oid);
        map.put("Is_O", Is_O);

        for (SlotShopInfoBean slotShopInfoBean : dllist) {
            dlStringBuilder.append(slotShopInfoBean.getSlot()).append(slotShopInfoBean.getCount()).append(slotShopInfoBean.getZdcount()).append(slotShopInfoBean.getTypes()).append("|");
            rtStringBuilder.append(slotShopInfoBean.getTimes());
        }

        String dlStr = dlStringBuilder.toString();
        if (dlStr.length() > 0 && dlStr.lastIndexOf("|") == dlStr.length()) {
            dlStr = dlStr.substring(0, dlStr.length() - 1);  // 去掉最后一个字段（|）
        }
        map.put("dl", dlStr);
        map.put("RT", rtStringBuilder.toString());
        String data = GsonUtils.toJson(map);
        L.i("解析好的出货信息", data);
        final String CHECKOUT_NOITIFY = "rkt/mch/checkoutnotify/";//上传串口信息
        try {
            if (mqttClient != null && mqttClient.isConnected()) {
                MqttMessage message = new MqttMessage();
                message.setPayload(data.getBytes());
                mqttClient.publish(CHECKOUT_NOITIFY, message, null, new IMqttActionListener() {
                    @Override
                    public void onSuccess(IMqttToken asyncActionToken) {
                        L.i(String.format("Mqtt消息发送成功\ntopic=%s\nmsg=%s", CHECKOUT_NOITIFY, message));
                    }

                    @Override
                    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                        L.e(String.format("Mqtt消息发送失败\ntopic=%s\nmsg=%s\nexception=%s", CHECKOUT_NOITIFY, message, exception.toString()));
                    }
                });
            } else {
                L.e(String.format("Mqtt发送消息异常\ntopic=%s\nmsg=%s\nexception=%s", CHECKOUT_NOITIFY, data, "mqtt 不在线"));

            }
        } catch (MqttException exception) {
            L.e(String.format("Mqtt发送消息异常\ntopic=%s\nmsg=%s\nexception=%s", CHECKOUT_NOITIFY, data, exception.toString()));
        } finally {
            dllist.clear();
        }
    }

    /**
     * 温控板子 版本信息
     *
     * @return
     */
    public HashMap<String, String> BzVersion() {
        HashMap<String, String> map = new HashMap<>();
        map.put("MV", SharedUtils.getInstance().getString("MV", ""));
        map.put("T", SharedUtils.getInstance().getString("T", ""));
        map.put("Fir", SharedUtils.getInstance().getString("Fir", ""));
        map.put("Sec", SharedUtils.getInstance().getString("Sec", ""));
        map.put("Thi", SharedUtils.getInstance().getString("Thi", ""));
        return map;
    }

    /**
     * 10 0E 02
     * 04
     * 01
     * 00
     * 00
     * 01
     * 13 0B 1D 13 0C 05 1A 9F
     * 第4位	掉货检测是否在线，3-在线，4-不在线	十六进制
     * 01	第5位	出货货到数量	十六进制
     * 00	第6位	货道号	十六进制
     * 00	第7位	掉货检测检测数量	十六进制
     * 02	第8位	电机转动次数
     * 19	第15位	第一个电机转动时间
     */

    public static List<SlotShopInfoBean> dllist = new ArrayList<>();

    /**
     * 解析转动货道的信息并添加到List中
     *
     * @param date     货道转动完成返回的指令
     * @param Slottype 货道类型
     */
    public void analyzeSlot(byte[] date, int Slottype) {

        Is_O = String.valueOf(Integer.parseInt(ByteUtils.byteToHex(date[3]), 16));
        int turnNumber = Integer.parseInt(ByteUtils.byteToHex(date[7]), 16); // 电机转动次数
//        前三位表示货道编号 第四位表示货道检测数量 第五位表示电机转动数量 最后一位表示货道类型
        int outGoodsAisle = ((Integer.parseInt(ByteUtils.byteToHex(date[0])) - 10) * 100) + Integer.parseInt(ByteUtils.byteToHex(date[5]), 16) + 1;
        L.i(String.format("outGoodsAisle:%s", outGoodsAisle));

        int type = 0;
        if (Slottype == 21001 || Slottype == 0) {  //弹簧货到
            type = 0;
        } else if (Slottype == 21002 || Slottype == 2) {//蛇形货道
            type = 2;
        } else if (Slottype == 21003 || Slottype == 1) {//电磁锁
            type = 1;
        } else {
            L.i("--货道类型异常- ", outGoodsAisle);
        }
        StringBuffer outGoodsAisleBuffer;
        if (outGoodsAisle < 10) {
            outGoodsAisleBuffer = new StringBuffer().append("00").append(outGoodsAisle);
        } else if (outGoodsAisle < 100) {
            outGoodsAisleBuffer = new StringBuffer().append("0").append(outGoodsAisle);
        } else {
            outGoodsAisleBuffer = new StringBuffer().append(outGoodsAisle);
        }
        L.i(String.format("outGoodsAisleBuffer:%s", outGoodsAisleBuffer));

        int downNum = Integer.parseInt(ByteUtils.byteToHex(date[6]), 16);

        SlotShopInfoBean slotShopInfoBean = new SlotShopInfoBean();
        slotShopInfoBean.setSlot(outGoodsAisleBuffer.toString()); // 货道号
        slotShopInfoBean.setCount(downNum);
        slotShopInfoBean.setTypes(type); // 货道类型
        slotShopInfoBean.setZdcount(turnNumber);
        if (dllist == null) {
            dllist = new ArrayList<>();
        }
        StringBuffer timesbuf = new StringBuffer();
        for (int i = 0; i < turnNumber; i++) {
            timesbuf.append(ByteUtils.byteToHex(date[i + 14]));
        }
        if (turnNumber == 0) {
            slotShopInfoBean.setTimes("00"); // 转动时间
        } else {
            slotShopInfoBean.setTimes(timesbuf.toString()); // 转动时间
        }
        L.i("出货指令=" + date,
                "解析详情", "掉货检测是否在线 " + Is_O + "==========" + (Is_O.equals("3") ? "在线" : "离线")
                        + "=货道号=" + slotShopInfoBean.getSlot() +
                        "=掉货检测数量=" + slotShopInfoBean.getCount() +
                        "-电机转动次数-" + slotShopInfoBean.getZdcount() + "==转动时间-" + slotShopInfoBean.getTimes());

        dllist.add(slotShopInfoBean);
        L.i(String.format("dllist:%s", dllist.toString()));
    }

    /**
     * 解析转动货道的信息并添加到List中
     *
     * @param date     货道转动完成返回的指令
     * @param Slottype 货道类型
     */
    public void analyzeSlotTest(byte[] date, int Slottype) {

        String Is_O = String.valueOf(Integer.parseInt(ByteUtils.byteToHex(date[3]), 16));
        int turnNumber = Integer.parseInt(ByteUtils.byteToHex(date[7]), 16); // 电机转动次数
//        前三位表示货道编号 第四位表示货道检测数量 第五位表示电机转动数量 最后一位表示货道类型
        int outGoodsAisle = ((Integer.parseInt(ByteUtils.byteToHex(date[0])) - 10) * 100) + Integer.parseInt(ByteUtils.byteToHex(date[5]), 16) + 1;
        L.i(String.format("outGoodsAisle:%s", outGoodsAisle));

        int type = 0;
        if (Slottype == 21001 || Slottype == 0) {  //弹簧货到
            type = 0;
        } else if (Slottype == 21002 || Slottype == 2) {//蛇形货道
            type = 2;
        } else if (Slottype == 21003 || Slottype == 1) {//电磁锁
            type = 1;
        } else if (Slottype == 21004 || Slottype == 3) {//推板
            type = 3;
        } else {
            L.i("--货道类型异常- ", outGoodsAisle);
        }
        StringBuffer outGoodsAisleBuffer;
        if (outGoodsAisle < 10) {
            outGoodsAisleBuffer = new StringBuffer().append("00").append(outGoodsAisle);
        } else if (outGoodsAisle < 100) {
            outGoodsAisleBuffer = new StringBuffer().append("0").append(outGoodsAisle);
        } else {
            outGoodsAisleBuffer = new StringBuffer().append(outGoodsAisle);
        }
        L.i(String.format("outGoodsAisleBuffer:%s", outGoodsAisleBuffer));

        int downNum = Integer.parseInt(ByteUtils.byteToHex(date[6]), 16);

        SlotShopInfoBean slotShopInfoBean = new SlotShopInfoBean();
        slotShopInfoBean.setSlot(outGoodsAisleBuffer.toString()); // 货道号
        slotShopInfoBean.setCount(downNum);
        slotShopInfoBean.setTypes(type); // 货道类型
        slotShopInfoBean.setZdcount(turnNumber);
        StringBuffer timesbuf = new StringBuffer();
        for (int i = 0; i < turnNumber; i++) {
            timesbuf.append(ByteUtils.byteToHex(date[i + 14]));
        }
        if (turnNumber == 0) {
            slotShopInfoBean.setTimes("00"); // 转动时间
        } else {
            slotShopInfoBean.setTimes(timesbuf.toString()); // 转动时间
        }
        L.i("出货指令=" + date,
                "解析详情", "掉货检测是否在线 " + Is_O + "==========" + (Is_O.equals("3") ? "在线" : "离线")
                        + "=货道号=" + slotShopInfoBean.getSlot() +
                        "=掉货检测数量=" + slotShopInfoBean.getCount() +
                        "-电机转动次数-" + slotShopInfoBean.getZdcount() + "==转动时间-" + slotShopInfoBean.getTimes());
    }

}
